package com.ttxs.common.security.feign;

import com.ttxs.common.core.constant.SecurityConstant;
import com.ttxs.common.core.properties.FeignHeaderProperties;
import com.ttxs.common.core.utils.ServletUtils;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import javax.servlet.http.HttpServletRequest;
import java.util.Objects;
import java.util.Set;

/**
 * feign 请求拦截器
 * 通过open feign调用微服务时，默认不传递敏感的请求头信息，通过该拦截器统一添加需要传递的请求头信息
 * 可用在在springboot配置文件中配置需要传递的header name
 *
 * @author ttxs
 */
public class FeignRequestInterceptor implements RequestInterceptor {
    private static final Logger log = LoggerFactory.getLogger(FeignRequestInterceptor.class);
    @Autowired
    private FeignHeaderProperties feignHeaderProperties;
    private static final String LOG_PREFIX = "feign inteceptor:";
    @Override
    public void apply(RequestTemplate requestTemplate) {
        HttpServletRequest request = ServletUtils.getRequest();
        log.info("{} context path:\t {}", LOG_PREFIX, request.getContextPath());
        log.info("{} url: \t{}", LOG_PREFIX, request.getRequestURI());
        if (Objects.nonNull(request)) {
            // 获取需要传递的header，例如token等
            Set<String> includes = feignHeaderProperties.getIncludes();
            // 添加安全key到请求头，模拟从网关访问
            includes.add(SecurityConstant.SECRET_KEY);

            if (!includes.isEmpty()) {
                includes.forEach(item -> {
                    requestTemplate.header(item, request.getHeader(item));
                });
            }
            // 移除header
            Set<String> excludes = feignHeaderProperties.getExcludes();
            if(!excludes.isEmpty()) {
                excludes.forEach(item -> {
                    requestTemplate.removeHeader(item);
                });
            }

            if(includes.isEmpty()) {
                log.warn("{} include headers is empty!", LOG_PREFIX);
            }
            if (log.isInfoEnabled()) {
                log.info("{} include headers:{}", LOG_PREFIX, includes);
                log.info("{} exclude headers:{}", LOG_PREFIX, excludes);
            }
        }
    }


}